package com.arofoxmsn.services;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.arofoxmsn.model.User;
import com.arofoxmsn.model.UserState;
import com.arofoxmsn.model.comunication.MobilePhone;
import com.arofoxmsn.model.identifiedObject.MyObject;
import com.arofoxmsn.model.location.Location;
import com.arofoxmsn.model.profile.Profile;
import com.arofoxmsn.model.userstate.AbstractUserState;
import com.arofoxmsn.model.userstate.AvaibleUserState;
import com.arofoxmsn.repository.UserTable;
import com.arofoxmsn.repository.location.LocationTable;
import com.arofoxmsn.utils.FlashMessage;
import com.arofoxmsn.utils.MathTools;
import com.arofoxmsn.utils.ParametersTool;

public class UserService {
	
	private static final double DEFAULT_RATIO = 1.4;
	
	/**
	 * this method is in charge of creating a user into data base. It checks each one
	 * of mandatory parameters  in order to return any fail to mandatory fields
	 * @param displayName
	 * @param currentLocation
	 * @param profile
	 * @param mobile
	 * @param myObject
	 * @param state
	 * @return FlashMessage with the result of the action
	 */
	public static FlashMessage creatingUser(String displayName, Location currentLocation, Profile profile, 
			MobilePhone mobile, MyObject myObject, AbstractUserState state){
		
		//Check mandatory fields
		Map<String,Object> mandatoryFields = new HashMap<String, Object>();
		mandatoryFields.put("Current Location", currentLocation);
		mandatoryFields.put("Mobile", mobile);
		mandatoryFields.put("Identify Object", myObject);
		mandatoryFields.put("User State", state);
		
		String wrongParameters = ParametersTool.testMandatoryFields(mandatoryFields);
		
		if(wrongParameters != null){
			wrongParameters = "Please check following parameters: \n"+wrongParameters;
			FlashMessage flash = new FlashMessage(FlashMessage.Type.OK, wrongParameters);
			return flash;
		}
		
		//Create and saving user
		User user = new User(displayName, currentLocation, profile, mobile, myObject, state, UserState.ACTIVE);
		UserTable table = new UserTable();
		return table.save(user);
	}
	/**
	 * this method is in charge of updating user position. It update current position
	 * attribute for a given user.
	 * @param user
	 * @param location
	 * @return Flash Message with the code and message with the result of the action
	 */
	public static FlashMessage setUserPossition(User user, Location location){
		
		Map<String,Object> mandatoryFields = new HashMap<String, Object>();
		mandatoryFields.put("User", user);
		mandatoryFields.put("Location", location);
		
		String wrongParameters = ParametersTool.testMandatoryFields(mandatoryFields);
		
		if(wrongParameters != null){
			return new FlashMessage(FlashMessage.Type.ERROR, "Please check following parameters: "+wrongParameters);
		}
		user.setCurrentLocation(location);
		UserTable table = new UserTable();
		return table.save(user);
	
	}
	/**
	 * 
	 * lazy method to update a user location.
	 * @param userId
	 * @param latitud
	 * @param longitud
	 * @return
	 * @see public FlashMessage setUserPossition(User user, Location location)
	 */
	public static FlashMessage setUserPossition(long userId, double latitud, double longitud){
		UserTable userTable = new UserTable();
		User user = userTable.retrieveById(userId);
		Location location = user.getCurrentLocation();
		location.setLat(latitud);
		location.setLon(longitud);
		return setUserPossition(user, location);
	}
	/**
	 * this message is an API for a quick user creation. It just takes as parameters
	 * the display message and 
	 * @param displayName
	 * @param latitud
	 * @param longitud
	 * @param mobileNumber
	 * @return
	 */
	public static FlashMessage creatingLazyUser(String displayName, String latitud, String longitud, String mobileNumber){
		
		Location loc = new Location();
		try{
			double longi = Double.valueOf(longitud);
			double latit = Double.valueOf(latitud);
			loc.setLat(latit);
			loc.setLon(longi);
		}catch(Exception e){
			return new FlashMessage(FlashMessage.Type.ERROR, "Check Geo Position parammeters");
		}
		
		MobilePhone mobile = new MobilePhone();
		mobile.setDescription(mobileNumber);
		
		MyObject myObject = new MyObject();
		myObject.setDescription("Flor");
		
		return creatingUser(displayName, loc, null,mobile, myObject, new AvaibleUserState());
	}
	/**
	 * this method is in charge of retrieve all user that could be near of given user
	 * @param user
	 * @return
	 */
	public static List<User> getNearUsers(User user){
		try{
			LocationTable table = new LocationTable();
			List<Location> locationCadidates = table.retrieveCandidates(user.getCurrentLocation());
			UserTable userTable = new UserTable();
			List<User> candidates = userTable.retrieveCandidates(locationCadidates, user.getId());
			return MathTools.filterUsers(candidates, user.getCurrentLocation(), DEFAULT_RATIO);
		}catch(Exception e){
			e.printStackTrace();
			return  null;
		} 
	}
	/**
	 * <b>Overloaded</b>
	 * @see public static List<User> getNearUsers(User user)
	 * @param userId
	 * @return
	 */
	public static List<User> getNearUsers(long userId){
		UserTable table = new UserTable();
		User current = table.retrieveById(userId);
		if(current == null)
			return null;
		return getNearUsers(current);
	}
	
}
